package geektime.spring.springbucks.service;

import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.exact;

import geektime.spring.springbucks.model.Coffee;
import geektime.spring.springbucks.repository.CoffeeRepository;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CoffeeService {

  private static final String CACHE = "springbucks-coffee";

  @Autowired
  private CoffeeRepository coffeeRepository;

  @Autowired
  private RedisTemplate<String, Coffee> redisTemplate;

  public List<Coffee> findAllCoffee() {
    return coffeeRepository.findAll();
  }

  public Optional<Coffee> findOneCoffee(String name) {
    HashOperations<String, String, Coffee> opsForHash = redisTemplate
        .opsForHash();
    if (redisTemplate.hasKey(CACHE) && opsForHash.hasKey(CACHE, name)) {
      log.info("Get coffee {} from Redis.", name);
      return Optional.of(opsForHash.get(CACHE, name));
    }

    ExampleMatcher matcher = ExampleMatcher.matching()
        .withMatcher("name", exact().ignoreCase());
    Optional<Coffee> coffee = coffeeRepository
        .findOne(Example.of(Coffee.builder().name(name).build(), matcher));
    log.info("Coffee Found:{}", coffee);
    if (coffee.isPresent()) {
      log.info("Put coffee {} to Redis.", name);
      opsForHash.put(CACHE, name, coffee.get());
      redisTemplate.expire(CACHE, 1, TimeUnit.MINUTES);
    }
    return coffee;
  }
}
